﻿// This file is part of Code4Public (http://code4public.codeplex.com)
// Copyright 2011 Sina Iravanian - <sina@sinairv.com>
//
// This source file(s) may be redistributed, altered and customized
// by any means PROVIDING the authors name and all copyright
// notices remain intact.
// THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED. USE IT AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO
// LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
// ------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Xml.Linq;
using Code4Public.Utils;
using YAXLib;

namespace Code4Public.Settings
{
    [YAXCustomSerializer(typeof(ColorProfileSerializer))]
    public class ColorProfile
    {
        public string Name { get; private set; }

        private readonly Dictionary<string, GroupProperties> m_dicGroupProperties = new Dictionary<string, GroupProperties>();

        public ColorProfile(string name)
        {
            Name = name;
        }

        public bool Add(string name, Color color, bool bold, bool italic)
        {
            if (m_dicGroupProperties.ContainsKey(name))
                return false;

            m_dicGroupProperties.Add(name, new GroupProperties() { Color = color, Bold = bold, Italic = italic } );
            return true;
        }

        public bool Contains(string groupName)
        {
            return m_dicGroupProperties.ContainsKey(groupName);
        }

        public bool TryGetProperties(string groupName, out GroupProperties props)
        {
            props = null;
            if (!Contains(groupName))
                return false;

            props = m_dicGroupProperties[groupName];
            return true;
        }

        public bool TryGetColor(string groupName, out Color color)
        {
            color = Color.White;
            if (!Contains(groupName))
                return false;

            color = m_dicGroupProperties[groupName].Color;
            return true;
        }

        public IEnumerable<KeyValuePair<string, GroupProperties>> GroupColors
        {
            get
            {
                return m_dicGroupProperties;
            }
        }

        public class GroupProperties
        {
            public bool Bold { get; set; }
            public bool Italic { get; set; }
            public Color Color { get; set; }
        }
    }

    internal class ColorProfileSerializer : ICustomSerializer<ColorProfile>
    {
        public ColorProfile DeserializeFromElement(XElement element)
        {
            var attrName = element.Attribute("name");
            if(attrName == null || String.IsNullOrEmpty(attrName.Value))
                throw new YAXAttributeMissingException("name");

            var profile = new ColorProfile(attrName.Value);
            foreach (var childElem in element.Elements())
            {
                var childName = childElem.Name.ToString().ToLower();
                if(childName == "coloring")
                {
                    string name = null;
                    Color color = Color.Black;
                    bool bold = false, italic =false;
                    foreach(var childAttr in childElem.Attributes())
                    {
                        var coloringAttrName = childAttr.Name.ToString().ToLower();
                        switch (coloringAttrName)
                        {
                            case "name":
                                name = childAttr.Value;
                                break;
                            case "color":
                                if(!ColorUtils.TryParseColor(childAttr.Value, out color))
                                {
                                    throw new YAXBadlyFormedInput(
                                        String.Format("{0}#{1}", childName, coloringAttrName), 
                                        childAttr.Value);
                                }
                                break;
                            case "bold":
                                if (!TryConvertStringToBool(childAttr.Value, out bold))
                                {
                                    throw new YAXBadlyFormedInput(
                                        String.Format("{0}#{1}", childName, coloringAttrName),
                                        childAttr.Value);
                                }
                                break;
                            case "italic":
                                if (!TryConvertStringToBool(childAttr.Value, out italic))
                                {
                                    throw new YAXBadlyFormedInput(
                                        String.Format("{0}#{1}", childName, coloringAttrName),
                                        childAttr.Value);
                                }
                                break;
                        }
                    }

                    if(String.IsNullOrEmpty(name))
                    {
                        throw new YAXAttributeMissingException("name");
                    }

                    profile.Add(name, color, bold, italic);
                }
            }

            return profile;
        }

        private static bool TryConvertStringToBool(string str, out bool result)
        {
            str = str.ToLower().Trim();
            switch (str)
            {
                case "true":
                case "yes":
                    result = true;
                    return true;
                case "false":
                case "no":
                    result = false;
                    return true;
                default:
                    result = false;
                    return false;

            }
        }

        public void SerializeToElement(ColorProfile objectToSerialize, XElement elemToFill)
        {
            var assignments = new List<XElement>();

            foreach (var pair in objectToSerialize.GroupColors)
            {
                assignments.Add(new XElement("Coloring",
                    new XAttribute("name", pair.Key),
                    new XAttribute("color", "#" + ColorUtils.ColorTo6CharString(pair.Value.Color)),
                    new XAttribute("bold", pair.Value.Bold),
                    new XAttribute("italic", pair.Value.Italic)
                ));
            }

            elemToFill.Add(new XAttribute("name", objectToSerialize.Name),
                assignments);
        }

        public ColorProfile DeserializeFromAttribute(XAttribute attrib)
        {
            throw new NotImplementedException();
        }

        public ColorProfile DeserializeFromValue(string value)
        {
            throw new NotImplementedException();
        }

        public void SerializeToAttribute(ColorProfile objectToSerialize, XAttribute attrToFill)
        {
            throw new NotImplementedException();
        }

        public string SerializeToValue(ColorProfile objectToSerialize)
        {
            throw new NotImplementedException();
        }
    }
}
